/*
 * A4CANBusData.cpp
 *
 *  Created on: Jul 9, 2011
 *      Author: matthew
 */

#include "A4CANBusData.h"

int htoi(char *strHex, unsigned int *nResult)
{
    unsigned int nTempResult = 0;
    unsigned int nIndex = 0;

    if(strHex[nIndex] == '0' && (strHex[nIndex+1]=='x' || strHex[nIndex+1]=='X')) nIndex+=2;

    while(strHex[nIndex]!='\0')
    {
       if (nTempResult > (UINT_MAX / 16))
    	   return -1;
       else if(strHex[nIndex] >= '0' && strHex[nIndex] <='9'){
    	   nTempResult = nTempResult * 16 + strHex[nIndex] - '0';
       }
       else if(strHex[nIndex]>='A' && strHex[nIndex] <='F'){
    	   nTempResult = nTempResult * 16 + strHex[nIndex] - 'A' + 10;
       }
       else if(strHex[nIndex]>='a' && strHex[nIndex] <='f'){
    	   nTempResult = nTempResult * 16 + strHex[nIndex] - 'a' + 10;
       } else
    	   return -1;
       nIndex++;
    }
    (*nResult) = nTempResult;

    return 0;
}

void CA4CANBusData::AddRawData(string strID, float fTime, vector<unsigned char> data){
	this->AddData(strID, fTime, data);
}

void CA4CANBusData::AddRawData(string strID, float fTime, string strData){
	vector<unsigned char> data;
	char *pstrData = new char[strData.size() + 1],
	     *pstrTok;
	strcpy(pstrData, strData.c_str());

	pstrTok = strtok(pstrData, " ,\t\r\n");
	while (pstrTok != NULL)
	{
		unsigned int nData;
		if (htoi(pstrTok, &nData) != 0)
			nData = 0;
		if (nData > 255)
			nData = 0;
		data.push_back((unsigned char)nData);
		pstrTok = strtok(NULL, " ,\t\r\n");
	}
	this->AddData(strID, fTime, data);
}

string CA4CANBusData::GetRawDataHexString(unsigned int nIDIndex, unsigned int nElementIndex){
	string strRawDataHex;
	vector<unsigned char> RawData;

	if (nIDIndex >= this->GetNumIDs())
		return string("Error");
	else if (nElementIndex >= this->GetNumDataEntriesForIndex(nIDIndex))
		return string("Error");

	RawData = this->GetData(nIDIndex, nElementIndex);

	for (unsigned int nCounter = 0; nCounter < RawData.size(); nCounter++)
	{
		char strHexBytes[256];
		snprintf(strHexBytes, 256, "\t%x", RawData.at(nCounter));
		strRawDataHex.append(strHexBytes);
	}

	return strRawDataHex;
}

string CA4CANBusData::GetRawDataDecString(unsigned int nIDIndex, unsigned int nElementIndex){
	string strRawDataDec;
	vector<unsigned char> RawData;

	if (nIDIndex >= this->GetNumIDs())
		return string("Error");
	else if (nElementIndex >= this->GetNumDataEntriesForIndex(nIDIndex))
		return string("Error");

	RawData = this->GetData(nIDIndex, nElementIndex);

	for (unsigned int nCounter = 0; nCounter < RawData.size(); nCounter++)
	{
		char strDecBytes[256];
		snprintf(strDecBytes, 256, "\t%d", RawData.at(nCounter));
		strRawDataDec.append(strDecBytes);
	}

	return strRawDataDec;
}

void CA4CANBusData::PopulateWithDataFields(CA4CANDataFields *pCopyOfData){
	for (unsigned int nOuterCounter = 0; nOuterCounter < this->GetNumIDs(); nOuterCounter++){
		string strID = this->GetID(nOuterCounter);
		for (int nInnerCounter = 0; nInnerCounter < this->GetNumDataEntriesForIndex(nOuterCounter); nInnerCounter++){
			vector<unsigned char> RawData = this->GetData(nOuterCounter, nInnerCounter);
			float fTimestamp = this->GetTimestamp(nOuterCounter, nInnerCounter);
			vector<int> DataFields = ConvertToDataFields(strID, RawData);
			pCopyOfData->AddData(strID, fTimestamp, DataFields);
		}
	}
}

vector<int> CA4CANBusData::ConvertToDataFields(string strID, vector<unsigned char> RawData){

	if (strID.compare("005") == 0){
		return ConvertToDataFieldFor0x005(RawData);
	} else if (strID.compare("050") == 0) {
		return ConvertToDataFieldFor0x050(RawData);
	} else if (strID.compare("0C2") == 0) {
		return ConvertToDataFieldFor0x0C2(RawData);
	} else if (strID.compare("1A0") == 0) {
		return ConvertToDataFieldFor0x1A0(RawData);
	} else if (strID.compare("280") == 0) {
		return ConvertToDataFieldFor0x280(RawData);
	} else if (strID.compare("288") == 0) {
		return ConvertToDataFieldFor0x288(RawData);
	} else if (strID.compare("320") == 0) {
		return ConvertToDataFieldFor0x320(RawData);
	} else if (strID.compare("380") == 0) {
		return ConvertToDataFieldFor0x380(RawData);
	} else if (strID.compare("38A") == 0) {
		return ConvertToDataFieldFor0x38A(RawData);
	} else if (strID.compare("420") == 0) {
		return ConvertToDataFieldFor0x420(RawData);
	} else if (strID.compare("440") == 0) {
		return ConvertToDataFieldFor0x440(RawData);
	} else if (strID.compare("480") == 0) {
		return ConvertToDataFieldFor0x480(RawData);
	} else if (strID.compare("488") == 0) {
		return ConvertToDataFieldFor0x488(RawData);
	} else if (strID.compare("4A0") == 0) {
		return ConvertToDataFieldFor0x4A0(RawData);
	} else if (strID.compare("4A8") == 0) {
		return ConvertToDataFieldFor0x4A8(RawData);
	} else if (strID.compare("520") == 0) {
		return ConvertToDataFieldFor0x520(RawData);
	} else if (strID.compare("540") == 0) {
		return ConvertToDataFieldFor0x540(RawData);
	} else if (strID.compare("580") == 0) {
		return ConvertToDataFieldFor0x580(RawData);
	} else if (strID.compare("588") == 0) {
		return ConvertToDataFieldFor0x588(RawData);
	} else if (strID.compare("5A0") == 0) {
		return ConvertToDataFieldFor0x5A0(RawData);
	} else if (strID.compare("5D0") == 0) {
		return ConvertToDataFieldFor0x5D0(RawData);
	} else if (strID.compare("5D2") == 0) {
		return ConvertToDataFieldFor0x5D2(RawData);
	} else if (strID.compare("5D8") == 0) {
		return ConvertToDataFieldFor0x5D8(RawData);
	} else if (strID.compare("5E0") == 0) {
		return ConvertToDataFieldFor0x5E0(RawData);
	}

	return vector<int>(0, 0);
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x005(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[5]);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x050(vector<unsigned char> RawData){
	vector<int> temp;
	// 4 Data bytes
	temp.push_back(RawData[2] >> 4);
	temp.push_back(RawData[2] & 0x0F);
	temp.push_back(RawData[3] >> 6);
	temp.push_back((RawData[3] >> 4) && 0x03);
	temp.push_back(RawData[3] & 0x0F);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x0C2(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes

	int nTemp = RawData[1] * 256 + RawData[0];
	if (nTemp > 32767)
		nTemp = 32767 - nTemp;
	temp.push_back(nTemp);

	nTemp = RawData[3] * 256 + RawData[2];
	if (nTemp > 32767)
		nTemp = 32767 - nTemp;
	temp.push_back(nTemp);

	temp.push_back(RawData[5] >> 4);
	temp.push_back(RawData[5] & 0x0F);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7] >> 4);
	temp.push_back(RawData[7] & 0x0F);
	temp.push_back(RawData[4]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x1A0(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[7] >> 4);
	temp.push_back(RawData[7] & 0x0F);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x280(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[7]);
	temp.push_back(RawData[3] * 256 + RawData[2]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[6]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x288(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x320(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x380(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[2]);
	temp.push_back(RawData[7]);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x38A(vector<unsigned char> RawData){
	vector<int> temp;
	// 4 Data bytes
	temp.push_back(RawData[0] >> 4);
	temp.push_back(RawData[0] & 0x0F);
	temp.push_back(RawData[2] >> 4);
	temp.push_back(RawData[2] & 0x0F);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[3]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x420(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x440(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[1]);
	temp.push_back(RawData[6] & 0x78 >> 3);
	temp.push_back(RawData[6] >> 7);
	temp.push_back(RawData[6] & 0x07);

	temp.push_back(RawData[0]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x480(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[7]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[6]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x488(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[1]);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x4A0(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x4A8(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[6] >> 4);
	temp.push_back(RawData[6] & 0x0F);
	temp.push_back(RawData[2]);  // Other signals in here
	temp.push_back(RawData[7]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x520(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x540(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0] >> 4);
	temp.push_back(RawData[0] & 0x0F);
	temp.push_back(RawData[7]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x580(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0] >> 4);
	temp.push_back(RawData[0] & 0x0F);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x588(vector<unsigned char> RawData){
	vector<int> temp;
	// 3 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x5A0(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x5D0(vector<unsigned char> RawData){
	vector<int> temp;
	// 6 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x5D2(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x5D8(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[0]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[5]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}

vector<int> CA4CANBusData::ConvertToDataFieldFor0x5E0(vector<unsigned char> RawData){
	vector<int> temp;
	// 8 Data bytes
	temp.push_back(RawData[5]);
	temp.push_back(RawData[0]);
	temp.push_back(RawData[3]);
	temp.push_back(RawData[1]);
	temp.push_back(RawData[2]);
	temp.push_back(RawData[4]);
	temp.push_back(RawData[6]);
	temp.push_back(RawData[7]);

	return temp;
}
